table of contents
POLL(2) | Руководство программиста Linux | POLL(2) |
ИМЯ¶
poll, ppoll - ожидает некоторое событие над файловым дескриптором
ОБЗОР¶
#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout); #define _GNU_SOURCE /* см. feature_test_macros(7) */ #include <poll.h> int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts, const sigset_t *sigmask);
ОПИСАНИЕ¶
Вызов poll() выполняет сходную с select(2) задачу: он ждёт пока один дескриптор из набора файловых дескрипторов не станет готов выполнить операцию ввода-вывода.
Отслеживаемый
набор
файловых
дескрипторов
задаётся в
аргументе
fds, который
представляет
собой
массив
структур:
struct pollfd {
int fd; /* файловый дескриптор */
short events; /* запрашиваемые события */
short revents; /* возвращённые события */ };
Вызывающий должен указать количество элементов в массиве fds в аргументе nfds.
В поле fd содержится файловый дескриптор открытого файла. Если значение поля отрицательно, то соответствующее поле events игнорируется, а полю revents возвращает ноль (простой способ игнорирования файлового дескриптора в одиночном вызове poll(): просто сделать значение поля fd отрицательным).
Поле events представляет собой входной параметр — битовую маску — указывающую на события, происходящие с файловым дескриптором fd, которые важны для приложения. Если значение поля равно нулю, то все события с fd игнорируются и revents возвращает ноль.
Поле revents представляет собой параметр-результат, в который ядро помещает информацию о произошедших событиях. В revents могут содержаться любые битовые флаги из задаваемых в events, или там может быть одно из значений: POLLERR, POLLHUP или POLLNVAL. Эти три битовых флага не имеют смысла в поле events, но будут установлены в поле revents, если соответствующее условие истинно.
Если ни одно из запрошенных событий с файловыми дескрипторами не произошло или не возникло ошибок, то poll() блокируется до их появления.
В аргументе timeout задаётся максимальное количество времени, на которое будет заблокирован poll() (в миллисекундах). Данное значение интервала будет округлено до точности системных часов, а из-за задержки при планировании в ядре блокирующий интервал будет немного больше. Отрицательное значение в timeout означает бесконечное ожидание. Значение timeout, равное нулю, приводит к немедленному завершению poll(), даже если ни один файловый дескриптор не готов.
Вот возможные биты, описанные в <poll.h>, которые могут быть установлены/получены в events и revents:
- POLLIN
- Есть данные для чтения.
- POLLPRI
- Есть срочные данные для чтения (например, внеполосные данные в сокете TCP; мастер псевдотерминала в пакетном режиме увидел изменение состояния подчинённого терминала).
- POLLOUT
- Теперь запись не приведёт к блокировке.
- POLLRDHUP (начиная с Linux 2.6.17)
- Удалённая сторона потокового сокета закрыла соединение, или отключила запись в одну сторону. Для использования данного определения должен быть определён макрос тестирования свойств _GNU_SOURCE (до включения каких-либо заголовочных файлов).
- POLLERR
- Состояние ошибки (указывается только как результат).
- POLLHUP
- Повесили трубку (hang up) (указывается только как результат).
- POLLNVAL
- Неверный запрос: дескриптор fd не открыт (указывается только как результат).
При компилировании с установленным _XOPEN_SOURCE также определены следующие значения, которые не передают дополнительной информации вне упомянутых выше битов:
- POLLRDNORM
- Эквивалентно POLLIN.
- POLLRDBAND
- Доступны для чтения приоритетные внутриполосные данные (в Linux, обычно, не используется).
- POLLWRNORM
- Эквивалентно POLLOUT.
- POLLWRBAND
- Можно писать приоритетные данные.
В Linux также есть POLLMSG, но он не используется.
ppoll()¶
Отношения между poll() и ppoll() аналогичны родству select(2) и pselect(2): как pselect(2), ppoll() позволяет приложению безопасно ждать, пока файловый дескриптор не станет готов или пока не будет получен сигнал.
Кроме различия в точности аргумента timeout вызов ppoll()
эквивалентен атомарному выполнению следующих вызовов:
ready = ppoll(&fds, nfds, timeout_ts, &sigmask);
sigset_t origmask;
int timeout;
timeout = (timeout_ts == NULL) ? -1 :
(timeout_ts.tv_sec * 1000 + timeout_ts.tv_nsec / 1000000);
sigprocmask(SIG_SETMASK, &sigmask, &origmask);
ready = poll(&fds, nfds, timeout);
sigprocmask(SIG_SETMASK, &origmask, NULL);
Смотрите в pselect(2) пояснения о необходимости ppoll().
Если значение аргумента sigmask равно NULL, то изменение маски сигналов не происходит (и поэтому ppoll() отличается от poll() только в точности аргумента timeout).
В
аргументе
timeout_ts
указывается
верхняя
граница
промежутка
времени, на
который
будет
заблокирован
ppoll(). Этот
аргумент
представляет
собой
указатель
на
структуру
следующего
вида:
struct timespec {
long tv_sec; /* секунды */
long tv_nsec; /* наносекунды */ };
Если значение timeout_ts равно NULL, то ppoll() может оставаться заблокированным бесконечно.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
При успешном выполнении возвращается положительное значение; оно означает количество структур, в которых поля revents имеют ненулевое значение (другими словами, тех дескрипторов, для которых возникли события или ошибки). Значение 0 означает, что время ожидания истекло, и нет готовых файловых дескрипторов. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
ОШИБКИ¶
ВЕРСИИ¶
Системный вызов poll() появился в Linux 2.1.23. Для старых ядер, в которых этот вызов отсутствует, glibc (и старая Linux libc) предоставляет обёрточную функцию poll(), которая эмулируется с помощью select(2).
Системный вызов ppoll() был добавлен в ядро Linux в версии 2.6.16. Библиотечный вызов ppoll() был добавлен в glibc 2.4.
СООТВЕТСТВИЕ СТАНДАРТАМ¶
Вызов poll() соответствует POSIX.1-2001. Вызов ppoll() есть только в Linux.
ЗАМЕЧАНИЯ¶
В некоторых реализациях определена нестандартная константа INFTIM со значением -1 для использования в качестве значения timeout в poll(). Эта константа отсутствует в glibc.
Замечания, касающиеся Linux¶
В Linux системный вызов ppoll() изменяет свой аргумент timeout_ts. Однако, обёрточная функция glibc скрывает это поведение с помощью локальной переменной для аргумента timeout, которая передаётся в системный вызов. Поэтому glibc функция ppoll() не изменяет свой аргумент timeout_ts.
ДЕФЕКТЫ¶
Смотрите описание ложных уведомлений о готовности в разделе ДЕФЕКТЫ справочной страницы select(2).
СМОТРИТЕ ТАКЖЕ¶
2012-05-05 | Linux |